
// <copyright file="IntelligentCopyHelper.cs" company="Subhadra Software Solutions">
//   
// </copyright>
// <summary>
//   Class IntelligentCopyHelper.
// </summary>

namespace SubhadraSolutions.Sharp.Utils.Reflection.Internal
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    ///     Class IntelligentCopyHelper.
    /// </summary>
    internal static class IntelligentCopyHelper
    {
        #region Public Methods and Operators

        /// <summary>
        /// Checks the list types.
        /// </summary>
        /// <param name="t1">
        /// The t1.
        /// </param>
        /// <param name="t2">
        /// The t2.
        /// </param>
        /// <returns>
        /// System.IsNullable{KeyValuePair{TypeType}}.
        /// </returns>
        public static KeyValuePair<Type, Type>? CheckListTypes(Type t1, Type t2)
        {
            Type lt1 = getListGenericType(t1, true);
            if (lt1 != null)
            {
                Type lt2 = getListGenericType(t2, false);
                if (lt2 != null)
                {
                    return new KeyValuePair<Type, Type>(lt1, lt2);
                }
            }

            return null;
        }

        /// <summary>
        /// Gets the non nullable value.
        /// </summary>
        /// <typeparam name="T">
        /// </typeparam>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <returns>
        /// The <see cref="T"/>.
        /// </returns>
        /// <remarks>
        /// [CAUTION]. [CALLED BY REFLECTION]
        /// </remarks>
        [CautionUsedByReflectionAttribute]
        public static T GetNonNullableValue<T>(T? value) where T : struct
        {
            return value == null ? default(T) : value.Value;
        }

        #endregion Public Methods and Operators

        #region Methods

        /// <summary>
        /// Gets the type of the list generic.
        /// </summary>
        /// <param name="t">
        /// The attribute.
        /// </param>
        /// <param name="acceptEnumerable">
        /// if set to <c>true</c> [accept enumerable].
        /// </param>
        /// <returns>
        /// Type.
        /// </returns>
        private static Type getListGenericType(Type t, bool acceptEnumerable)
        {
            if (t.IsGenericType)
            {
                Type acceptableType = acceptEnumerable ? typeof(IEnumerable<>) : typeof(IList<>);
                Type[] generics = t.GetGenericArguments();
                Type genericType = acceptableType.MakeGenericType(generics);
                if (genericType.IsAssignableFrom(t))
                {
                    return generics[0];
                }
            }

            return null;
        }

        #endregion Methods
    }
}